package com.apes.fn.server.pickUpCar.service;
import com.apes.fn.crm.customerExpand.FnCustomerExpandRepository;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.repository.ServicePlanRepository;
import com.apes.fn.server.servicePlan.service.AbstractPlan;
import com.apes.framework.util.*;
import com.apes.hr.base.model.Employee;
import com.apes.hr.base.repository.EmployeeRepository;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.rbac.model.Post;
import com.apes.scm.rbac.repository.PostRepository;
import com.apes.scm.rbac.repository.UserRepository;
import com.google.common.collect.Lists;
import java.util.Date;
import com.apes.framework.plugin.soe.metadata.Scene;
import com.google.common.collect.Sets;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.business.carAccident.modle.CarAccident;
import com.apes.fn.business.carAccident.modle.PickCarTypeAccident;
import com.apes.fn.business.carAccident.repository.CarAccidentRepository;
import com.apes.fn.business.fixedLoss.service.FixedLossToForeign;
import com.apes.fn.crm.customerExpand.FnCustomerExpand;
import com.apes.fn.crm.customerExpand.FnCustomerExpandService;
import com.apes.fn.server.pickUpCar.model.KeyNumber;
import com.apes.fn.server.pickUpCar.model.PickUpCar;
import com.apes.fn.server.pickUpCar.model.PickUpCarItem;
import com.apes.fn.server.pickUpCar.model.PickUpType;
import com.apes.fn.server.pickUpCar.repository.KeyNumberRepository;
import com.apes.fn.server.pickUpCar.repository.PickUpCarRepository;
import com.apes.fn.server.servicePlan.service.ServicePlanceService;
import com.apes.fn.server.transferVehicle.model.InnerPickDeliveryUpCar;
import com.apes.fn.server.transferVehicle.repository.InnerPickDeliveryUpCarRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.jpa.logger.ApesLogger;
import com.apes.framework.jpa.logger.ApesLoggerRepository;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Filter;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.express.FuncAlias;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.OutboxSubscriberService;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.pi.model.Timestamp;
import com.apes.pi.repository.TimestampRepository;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.AccessProvider;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.AccessProviderRepository;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.rbac.service.UserService;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.persistence.Transient;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wsj
 * @Classname PickUpCarService
 * @Description 接车单
 * @Date 2020/1/14 17:01
 */
@Service("pickUpCarService")
public class PickUpCarService extends DomainService {
    @Autowired
    private PickUpCarRepository pickUpCarRepository;
    @Autowired
    private KeyNumberRepository keyNumberRepository;
    @Autowired
    private EnumerationRepository enumerationRepository;
    @Autowired
    private PickUpCarDao pickUpCarDao;
    @Autowired
    private UserService userService;
    @Autowired
    private OutboxSubscriberService outbox;
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private EmployeeRepository employeeRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private DistributedLock distributedLock;


    /**
     * 防止门店,客户只穿了编码, 所以再查一次
     * @param request
     * @return
     */
    public PickUpCar save(SimpleRequest request) {
        //app 不传公司,需要去取门店得所属公司
        PickUpCar pickUpCar = updateOrInsertCustomerExpand(request);
        pickUpCar.setCompany(pickUpCar.getDept().getCompany());

        if(pickUpCar.getPickCarType() == null ) {
            Enumeration pickCarType =  SpringManager.getBean(EnumerationRepository.class).findOne("pickA");
            pickUpCar.setPickCarType(pickCarType);
        }
        //设置扩展表接车类型
        pickUpCar.setFnCustomerExpand(SpringManager.getBean(FnCustomerExpandService.class).saveFncustomerExpandPickUpType(pickUpCar));
        invoke("fn.customerCar.checkCarModelValid",MapUtil.mapper("jekunModelCode",pickUpCar.getFnCustomerExpand().getJekunModelCode()));

        pickUpCar.setState("approve");
        pickUpCar = pickUpCarRepository.saveAndFlush(pickUpCar);
        updateKeyNumber(pickUpCar,false);
        //接车时 回写车险报案单相关数据
        JSONObject data = new JSONObject();
        data.put("id", pickUpCar.getId());
        outbox.commonSendRequest("PickUpCarService.writeBackCarAccident", "JC" + pickUpCar.getId(), data);
        return pickUpCar;
    }


    @OutboxSubscriber(id="PickUpCarService.writeBackCarAccident", name="接车单回写报案单")
    private void writeBackCarAccident(OutboxPayloadWrapper wrapper) {
        JSONObject param = JSONObject.parseObject(wrapper.getPayload());
        PickUpCar pickUpCar = pickUpCarRepository.findOne(param.getString("id"));
        if (Objects.isNull(pickUpCar)) {
            throw new RuntimeException("未找到对应接车单数据!!!");
        }
        List<CarAccident> carAccident =
                SpringManager.getBean(CarAccidentRepository.class).findCarAccidentByCarNumber(pickUpCar.getLicenseNumber(), pickUpCar.getDept().getId());
        carAccident.forEach(
                item -> {
                    item.setCustomerExpand(pickUpCar.getFnCustomerExpand());
                    List<PickCarTypeAccident> list = pickUpCar.getPickUpTypes().stream().map(
                            pickUpType -> {
                                PickCarTypeAccident carTypeAccident = new PickCarTypeAccident();
                                carTypeAccident.setId(SpringManager.getBean(SequenceService.class).getId(PickCarTypeAccident.CONST_TABLE_NAME));
                                carTypeAccident.setCarAccident(item);
                                carTypeAccident.setPickUpType(pickUpType.getPickUpType());
                                carTypeAccident.setRemarks(pickUpType.getRemarks());
                                return carTypeAccident;
                            }
                    ).collect(Collectors.toList());
                    item.setTypeAccidents(list);
                    if ("store".equals(item.getState())){
                        item.setState("inStore");
                        item.setPickCarTime(pickUpCar.getCreateDate());
                    }
                    item.setRiskCar(pickUpCar.isRiskCar());
                    SpringManager.getBean(CarAccidentRepository.class).saveAndFlush(item);
                }
        );
    }

    /***
     * 功能： 修改
     * @param request
     * @return
     */
    public PickUpCar update(SimpleRequest request) {
        checkData(request);
        String id = request.get("id");
        PickUpCar pickUpCarTow = pickUpCarRepository.findOne(id);
        PickUpCar pickUpCar = request.getO(PickUpCar.class);

        pickUpCar.getPickUpTypes().forEach(item -> {
            String i = SpringManager.getBean(SequenceService.class).getId(PickUpType.CONST_TABLE_NAME);
            item.setId(i);
        });

        pickUpCar.getPickUpCarItem().forEach(item -> {
            String i = SpringManager.getBean(SequenceService.class).getId(PickUpCarItem.CONST_TABLE_NAME);
            item.setId(i);
        });
        pickUpCarTow.getPickUpTypes().clear();
        pickUpCarTow.getPickUpTypes().addAll(pickUpCar.getPickUpTypes());
        pickUpCarTow.setMileage(pickUpCar.getMileage());
        pickUpCarTow.setPickUpCarItem(pickUpCar.getPickUpCarItem());
        pickUpCarTow.setNote(pickUpCar.getNote());
        pickUpCarTow.setFuelMeter(pickUpCar.getFuelMeter());
        pickUpCarTow.setFaultDescription(pickUpCar.getFaultDescription());
        pickUpCarTow.setFnCustomerExpand(SpringManager.getBean(FnCustomerExpandService.class).saveFncustomerExpandPickUpType(pickUpCarTow));  //设置扩展表接车类型
        pickUpCarTow.setMileage(pickUpCar.getMileage());
        return  pickUpCarRepository.saveAndFlush(pickUpCarTow);
    }

    /***
     * 功能： 修改预计时间
     * @param request
     * @return
     */
    public Map updateEsTime(SimpleRequest request) {
        String id = request.get("id");
        Date esDate = request.get("estimateDate");
        PickUpCar pickUpCarTow = pickUpCarRepository.findOne(id);
        pickUpCarTow.setEstimateDate(esDate);
        pickUpCarTow = pickUpCarRepository.saveAndFlush(pickUpCarTow);
        return MapUtil.mapper("id",pickUpCarTow.getId(),"estimateDate",pickUpCarTow.getEstimateDate());
    }
    /***
     * 功能： 删除
     * @param request
     * @return
     * @throws RuntimeException
     */
    public PickUpCar delete(SimpleRequest request) throws RuntimeException {
        checkData(request);
        PickUpCar pickUpCar = request.getO(PickUpCar.class);
        pickUpCarRepository.delete(pickUpCar.getId());
        return pickUpCar;
    }

    private void checkData(SimpleRequest request) {
        String id = request.get("id");
        PickUpCar pickUpCar = pickUpCarRepository.findOne(id);
        // long versions = (int) request.get("version"); // 获取当前请求的版本信息
        if (pickUpCar == null) throw new RuntimeException("接车单【" + id + "】在系统中不存在。");
        // if (pickUpCar.getVersion() != versions) throw new RuntimeException("记录已更新或已删除，请重新提交！");  // 用于判断当前版本是否被修改
    }

    /**
     * 更新接车单转态
     * @param request
     * @return
     */

    public PickUpCar updateStates(SimpleRequest request) {
        String id = request.get("id");
        String operator = request.get("operator");
        String advanceRemark = request.getJO().getString("advanceRemark");
        //获取人员对象
        PartyRole partyRole = SpringManager.getBean(PartyRoleRepository.class).findOne(operator);
        if (partyRole == null) throw new RuntimeException("系统未存在该人员!!!请确认");
        Date date = new Date();//当前时间
        PickUpCar pickUpCar = pickUpCarRepository.findOne(id);
        //操作状态值 operateNumber (1:通知取车;2:确认交车;3:取消通知取车;4:终止接车单)
        int operateNumber = request.get("operateNumber");
        switch (operateNumber){
            case 1 :
                    if(pickUpCar.isNoticePickCar()) throw new  RuntimeException("该接车单已经通知取车!!请勿重复操作");
                    pickUpCar.setNoticePickCar(true);
                    pickUpCar.setNoticeDate(date);
                    pickUpCar.setNoticeUid(partyRole);
                break;
            case  2:
                if (!"approve".equals(pickUpCar.getState())) {
                    throw new RuntimeException("该接车单状态值不为审核状态,不能确认交车!!!");
                }
                // 在确认交车前,还需判断系统是否存在着未收车的内协交接车
                List <InnerPickDeliveryUpCar> deliveryUpCars =
                        SpringManager.getBean(InnerPickDeliveryUpCarRepository.class).findAll(JpaDsl.toCriteriaByEq("pickUpCar",pickUpCar));
                if (deliveryUpCars.size() >0 ) {
                    for (InnerPickDeliveryUpCar item : deliveryUpCars) {
                        if (!"confirm".equals(item.getState()) && !"repeal".equals(item.getState()) ) {
                            throw new RuntimeException("该车牌还有未完成的内协交接车单,内协交车单号: " + item.getId());
                        }
                    }
                }
                pickUpCar.setAdvanceRemark(advanceRemark);
                pickUpCar.setState("finish");
                pickUpCar.setFinishDate(date);
                pickUpCar.setFinishUid(partyRole);
                //确认交车 需释放钥匙号
                updateKeyNumber(pickUpCar,true);
                break;
            case 3:
                if(!pickUpCar.isNoticePickCar()) throw new  RuntimeException("该接车单未通知取车!!请勿重复操作");
                pickUpCar.setNoticePickCar(false);
                break;
            case 4:   //终止接车单释放钥匙号资源
                if (!"approve".equals(pickUpCar.getState())) {
                    throw new RuntimeException("该接车单状态值不为审核状态,不能终止!!!");
                }
                pickUpCar.setRepealDate(date);
                pickUpCar.setRepealUid(partyRole);
                pickUpCar.setState("repeal");
                updateKeyNumber(pickUpCar,true);
                break;
            default:
                throw new RuntimeException("没有对应的操作状态值!!!");
        }

        pickUpCar = pickUpCarRepository.saveAndFlush(pickUpCar);
        return  pickUpCar;
    }
    /**
     * 获取字段配置
     * @param request
     * @return
     */

    public JSONObject getConfigure(SimpleRequest request) {
        JSONObject result = new JSONObject();
        EnumerationRepository enumerationRepository = SpringManager.getBean(EnumerationRepository.class);
        List<Enumeration> list = enumerationRepository.findByType("personalItems");
        if (list.size() == 0) throw new RuntimeException("请定义随车物品该枚举!!!");
        JSONArray array = new JSONArray();
        array =  list.stream().map(
                item -> {
                    JSONObject object = new JSONObject();
                    object.put("name", item.getDescription());
                    return  object;
                }
        ).collect(Collectors.toCollection(JSONArray::new));
        result.put("personalItem", array);
        String deptId = request.get("deptId");
        String index = request.get("mark");
        if ("1".equals(index)) {
            Dept dept = SpringManager.getBean(DeptRepository.class).findOne(deptId);
            //根据门店和有效标记去钥匙表里面查找是否有可用钥匙号 如果没有 则批量插入随机生成钥匙号
            List<KeyNumber> keyNumberList = keyNumberRepository.findByDeptAndValid(dept,true);
            //如果钥匙号不够用,则需要批量插入五十个钥匙号
            if (keyNumberList == null || keyNumberList.size() == 0) {
                for (int i = 0; i < 50; i++) {
                    int keyCard=(int)(Math.random()*900)+100 + new Random().nextInt(1000);
                    KeyNumber keyNumber = new KeyNumber();
                    List<KeyNumber> keyList = keyNumberRepository.findAll(
                            JpaDsl.toCriteriaByEq("keyCard",keyCard,"dept",dept)
                    );
                    if (keyList.size() ==0) {
                        if (!result.containsKey("keyNumber")) {
                            //批量插入时第一个钥匙号封装到返回值里面
                            keyNumber.setValid(false);
                            result.put("keyNumber", keyCard);
                        }else {
                            keyNumber.setValid(true);
                        }
                        keyNumber.setDept(dept);
                        keyNumber.setKeyCard(keyCard);
                        keyNumber.setUpdateDate(new Date());
                        keyNumberRepository.saveAndFlush(keyNumber);
                    }
                }
            }else {
                result.put("keyNumber", keyNumberList.get(0).getKeyCard());
            }
        }
        long time = new Date().getTime();
        String uniqueCode = String.valueOf(time) + String.valueOf(new Random().nextInt(999));
        result.put("uniqueCode",uniqueCode);
        return result;
    }

    /***
     * 功能： 更新钥匙号 状态
     * @param pickUpCar
     * @return
     * @throws RuntimeException
     */
    private void updateKeyNumber(PickUpCar pickUpCar,boolean state) throws RuntimeException {
        KeyNumber keyNumber = keyNumberRepository.findByDeptAndKeyCard(pickUpCar.getDept(),pickUpCar.getKeyNumber());
        if (Objects.isNull(keyNumber)) {
            throw new RuntimeException("钥匙号对象为空!!!");
        }
        keyNumber.setValid(state);
        keyNumber.setUpdateDate(new Date());
        try {
            keyNumberRepository.saveAndFlush(keyNumber);
        } catch (Exception e) {
            throw  new RuntimeException ("释放钥匙号失败!!!");
        }
    }

    private void saveLog(JSONObject keyNumber) {
        Document document = new Document(keyNumber);
        mongoTemplate.getCollection("keyNumber").insertOne(document);
    }

    /***
     * 功能： 根据接车单查找接车单
     * @param request
     * @return
     * @throws RuntimeException
     */
    public Map findOneWithID(SimpleRequest request) throws Exception {
        JSONObject param = request.getJO();
        Map result ;
        String licenseNumber = param.getString("licenseNumber");
        String accessProvider = param.getString("accessProvider");
        AccessProvider provider = SpringManager.getBean(AccessProviderRepository.class).findOne(accessProvider);
        List<PickUpCar> list = queryPickUpCarWithAccessProviderOrLastGet(provider, licenseNumber);
        if (list.size() == 0) return   new HashMap();
        String id;
        try {
            //JSONObject.parseObject(JSONObject.toJSON(obj).toString())；
            PickUpCar pickUpCar = list.stream().max(
                    Comparator.comparing(PickUpCar::getCreateDate)
            ).get();
            id = pickUpCar.getId();
            result = MapUtil.mapped(pickUpCar);
        } catch (Exception e) {
            throw new RuntimeException("对象转换JSON失败,联系后台处理");
        }
        List<ApesLogger> loggers =
                SpringManager.getBean(ApesLoggerRepository.class).findAllByBusinessKeyAndAndBusinessTypeOrderByBusinessDateDesc(id,"PickUpCar");
        JSONArray array = loggers.stream().map(
                item -> {
                    JSONObject object = new JSONObject();
                    object.put("operator", getOperator(item.getOperator_id()).get("name"));
                    object.put("operateDate", item.getBusinessDate());
                    object.put("operate", item.getOperate());
                    return object;
                }
        ).collect(Collectors.toCollection(JSONArray::new));
        result.put("operateList", array);
        return  result;
    }

    /***
     * 得到过滤器
     */
    private Group getGroup(String company,String licensePlate,String pickCarType ) {
        Group group = new Group();
        List<Filter> groupFilter = JpaDsl.toFilter(
                "company.id", "IN",company,
                "licenseNumber","EQ",licensePlate,
                "pickCarType.id","EQ",pickCarType,
                "state","EQ","approve");
        groupFilter.get(0).setType("array");
        // groupFilter.get(1).setType("string");
        // groupFilter.get(2).setType("string");
        group.addFilters(groupFilter);
        return group;
    }

    /**
     * 判断
     * @param provider
     * @param licensePlate
     * @return
     */
    public boolean  judgeWhetherExist (AccessProvider provider ,String licensePlate) {
        List<PickUpCar> list = queryPickUpCarWithAccessProvider(provider, licensePlate);
        return list.size() >0;
    }

    /**
     * 根据接入商 查找 该接入商下该车牌对应得内协交车车
     * @param provider
     * @param licensePlate
     * @return
     */
    public List<InnerPickDeliveryUpCar> queryByAccessProvider(AccessProvider provider, String licensePlate) {
        List<PartyRole> companies = provider.getCompanys();
        String company = getCompanyString(companies);
        Group group = new Group();
        List<Filter> groupFilter = JpaDsl.toFilter(
                "otherSideDept.company.id", "IN",company,
                "licenseNumber","EQ",licensePlate,
                "state","EQ","get");
        groupFilter.get(0).setType("array");
        // groupFilter.get(1).setType("string");
        // groupFilter.get(2).setType("string");
        group.addFilters(groupFilter);
        return  SpringManager.getBean(InnerPickDeliveryUpCarRepository.class).findAll(
                JpaDsl.build(group, false)
        );
    }


    /**
     * 根据接入商 查找 该接入商下该车牌对应得接车单
     * @param provider
     * @param licensePlate
     * @return
     */
    public List<PickUpCar> queryPickUpCarWithAccessProvider(AccessProvider provider, String licensePlate) {
        List<PartyRole> companies = provider.getCompanys();
        String company = getCompanyString(companies);
        Enumeration pickCarType = SpringManager.getBean(EnumerationRepository.class).findOne("pickA");
        Group group = getGroup(company,licensePlate,pickCarType.getId());
        return  pickUpCarRepository.findAll(
                JpaDsl.build(group, false)
        );
    }

    /**
     * 根据接入商 查找 该接入商下该车牌对应得接车单(如果没有则返回最近一次接车)
     * @param provider
     * @param licensePlate
     * @return
     */
    public List<PickUpCar> queryPickUpCarWithAccessProviderOrLastGet(AccessProvider provider, String licensePlate) {
        List<PartyRole> companies = provider.getCompanys();
        String company = getCompanyString(companies);
        Enumeration pickCarType = SpringManager.getBean(EnumerationRepository.class).findOne("pickA");
        Group group = getGroup(company,licensePlate,pickCarType.getId());
        List<PickUpCar> pick = pickUpCarRepository.findAll(JpaDsl.build(group, false));
        if (pick.isEmpty()){
            PickUpCar pickUpCar = pickUpCarRepository.findAll(JpaDsl.toCriteria(
                    "company", "IN", companies,
                    "licenseNumber", "EQ", licensePlate,
                    "pickCarType.id", "EQ", pickCarType.getId()), new Sort(Sort.Direction.DESC, "createDate")).stream().findFirst().orElse(null);
            if (pickUpCar!=null)pick.add(pickUpCar);
        }

        return pick ;
    }

    /***
     * 保存会员和车辆数据
     */
    private PickUpCar updateOrInsertCustomerExpand(SimpleRequest request) {
        JSONObject tempJson = request.getJO();
        request.setData(null);
        tempJson.remove("company");
        request.setData(tempJson);

        PickUpCar pickUpCar = request.getO(PickUpCar.class);
        AccessProvider accessProvider = pickUpCar.getDept().getCompany().queryAccessProvider();
        //判断是否存在有效的接车单
        List<PickUpCar> upCar = queryPickUpCarWithAccessProvider(accessProvider, pickUpCar.getLicenseNumber());
        if (upCar.size() >0) {
            PickUpCar pick = upCar.get(0);
            throw new RuntimeException(pick.getDept().getName() + "已经存在" + pick.getLicenseNumber() + "的用户接车!!!!");
        }
        List<InnerPickDeliveryUpCar> innerPickDeliveryUpCarList = queryByAccessProvider(accessProvider, pickUpCar.getLicenseNumber());
        if (innerPickDeliveryUpCarList.size() >0) {
            InnerPickDeliveryUpCar innerPickDeliveryUpCar = innerPickDeliveryUpCarList.get(0);
            throw new RuntimeException(innerPickDeliveryUpCar.getOtherSideDept().getName() + "已经存在" + innerPickDeliveryUpCar.getLicenseNumber() + "的内协接车!!!!");
        }
        //正则表达是匹配
        String reg = "\\d{3}";
        String reg2 = "\\d{4}";
        String keyCode = String.valueOf(pickUpCar.getKeyNumber());
        if ((!keyCode.matches(reg))&&(!keyCode.matches(reg2))){
            throw new RuntimeException("钥匙号不符合规则!!!" + pickUpCar.getKeyNumber());
        }

        FnCustomerExpand customerExpand = findFnCustomerExpand(tempJson, pickUpCar);
        customerExpand.setCarModelService(SpringManager.getBean(FixedLossToForeign.class).getCarModelServiceLevel(customerExpand.getJekunModelCode()));
        pickUpCar.setFnCustomerExpand(customerExpand);

        return pickUpCar;
    }

    private FnCustomerExpand findFnCustomerExpand(JSONObject tempJson, PickUpCar pickUpCar) {
        Dept dept = pickUpCar.getDept();
        FnCustomerExpand customerExpand = SpringManager.getBean(ServicePlanceService.class)
                .findValidServiceFnCustomerExpand(dept, pickUpCar.getLicenseNumber());
        if (Objects.isNull(customerExpand)) {
            customerExpand = findCustomerExpandByCarAccident(dept, pickUpCar.getLicenseNumber());
        }
        customerExpand = this.invoke("fn.customerExpand.updateOrInsert", MapUtil.mapper(
                "customerExpand", customerExpand != null ? MapUtil.mapper("id", customerExpand.getId()) : null,
                "customer", tempJson.get("customerInfo"),
                "customerCar", tempJson.get("customerCar")
        ));
        return customerExpand;
    }

    /**
     * 补全操作员编码
     * @param operatorId
     * @return
     */
    private Map getOperator(Integer operatorId) {
        if (operatorId == null) return new HashMap();
        Object result = getUser(operatorId);
        return MapUtil.mapper("id", operatorId, "name", result != null ? ReflectUtil.getFieldValue(result, "name") : null);
    }

    /**
     * 根据车牌+门店查询有效的拓展信息
     */
    public List<FnCustomerExpand> findFnValidateCustomerExpandByDeptAndCarlicense(Dept dept,String carLicense){
        List<PickUpCar> pickUpCars =  pickUpCarRepository.findAll(JpaDsl.toCriteriaByEq("dept.id",dept.getId(),"fnCustomerExpand.carLicense",carLicense,"state","approve"));
        return pickUpCars.stream().map(PickUpCar::getFnCustomerExpand).collect(Collectors.toCollection(ArrayList::new));
    }


    /**
     * 根据车牌加门店 查询 车险报案定损有效的扩展信息
     */
    public FnCustomerExpand findCustomerExpandByCarAccident(Dept dept,String carLicense){
        List<CarAccident> carAccidents =
                SpringManager.getBean(CarAccidentRepository.class).findffectiveCarAccidentByCarNumber(carLicense,dept);
        if (carAccidents.size() > 0) {
            FnCustomerExpand customerExpand = carAccidents.stream()
                    .max(Comparator.comparing(CarAccident::getCreateDate))
                    .orElse(new CarAccident()).getCustomerExpand();
            return customerExpand;
        }else {
            return null;
        }

    }

    /**
     * 得到公司字符串
     */
    public String getCompanyString(List<PartyRole> company){
       if (company.size() == 0) throw new RuntimeException("无公司信息!!!");
       return company.stream().map(PartyRole::getId).collect(Collectors.joining(","));
    }

    /**
     * 根据唯一的车辆拓份(取消,因为会找到无效的接车单)，找到有效的接车单
     */
    public PickUpCar findValidatePickUpCarByFnCustomerExpand(Dept dept,FnCustomerExpand fnCustomerExpand){
        List<PickUpCar> pickUpCars = pickUpCarRepository.findAll(JpaDsl.toCriteriaByEq("dept.id",dept.getId(),"state","approve"));
        if(pickUpCars.size() > 1){
//            throw new RuntimeException("该门店存在多份接车信息，请检查");
            return pickUpCars.stream().findFirst().get();
        }else if(pickUpCars.size() != 1){
            return null;
        }
        return pickUpCars.stream().findFirst().get();
    }

    private PartyRole getEmployee(String employeeName){
        List<Employee> jiecr = employeeRepository.findByName(employeeName);
        if (jiecr.size() != 1)return null;
        return jiecr.get(0).getParty().getPartyRoleByType("Employee");
    }

    /**
     * App同步接车单
     */
    public List<PickUpCar> queryPickUpCar(SimpleRequest request){
        JSONObject jsonObject = request.getJO();
        Assert.isTrue(!StringUtils.isEmpty(jsonObject.getString("timestamp")), "时间戳不能为空!!!");
        Date timestamp = new Date(jsonObject.getLong("timestamp"));
        String id = jsonObject.getString("id"); //  最后更新ID
        int maxNum = jsonObject.getInteger("maxNum"); //单次请求最大条数
        return pickUpCarRepository.queryPickUpCar(timestamp, id, PageRequest.of(0, maxNum));
    }

    public void synPickUpCarToApp(SimpleRequest request) {
        Map newMap = new HashMap();
        newMap.put("method","fn.pickUpCar.queryPickUpCar");
        newMap.put("timestamp",new Date());
        // 调用App接口 通知接口
        String notifyTopic = "event:pi.app.synAppNotify";
        JSONObject notifyFlg = (JSONObject) EventUtil.sendSynEvent(this, notifyTopic, newMap).stream().findFirst().get();

    }

    /**
     * type ： pickUpType
     * 传入接车类型，获取接车类型
     * @param req
     * @return
     */
    public List<Map> qryPickUpType(SimpleRequest req){
        JSONObject jo = req.getJO();
        List<Enumeration> pickUpTypes = enumerationRepository.findByType(jo.getString("type"));
        if(pickUpTypes == null)
            return null;
        else
            return pickUpTypes.stream().map(enumeration -> {
            return MapUtil.mapper("key",enumeration.getId(),"value",enumeration.getDescription());
        }).collect(Collectors.toList());
    }

    public Map<String, Object> getPickUpCarWithId (SimpleRequest req) {
        JSONObject object = req.getJO();
        if (!object.containsKey("id")) {
            throw new RuntimeException("接车单号不能为空!!!");
        }
        return MapUtil.mapped(pickUpCarRepository.findOne(object.getString("id")));
    }


//    @OutboxSubscriber(name = "APP要求，接车单改变发信号量给APP")
//    public void sentSinalToAppForPickUpCar(PickUpCar pickUpCar){
//        this.invoke("pi.app.ext", MapUtil.mapper("headers",MapUtil.mapper("method","app暂未提供接口","action","post"),"body",MapUtil.mapper("yyerpApiName","fn.service.synPickUpCarForTimestamp","timestamp",pickUpCar.getLastUpdatedStamp())));
//    }

    public Map getAdvanceOrder(SimpleRequest re){
        String  id = re.getJO().getString("id");
        PickUpCar pickUpCar = pickUpCarRepository.findOne(id);
        if(pickUpCar == null) throw new RuntimeException("不存在的接车单号，参数有误：" +  id);

        Dept dept = pickUpCar.getDept();
        FnCustomerExpand fnCustomerExpand = pickUpCar.getFnCustomerExpand();

        JSONObject param = new JSONObject();
        param.put("FNCUSTOMEREXPAND",fnCustomerExpand.getId());
        param.put("DEPT",dept.getId());
        JSONArray array =  pickUpCarDao.qryAvanceOrder(param);

        List list = new ArrayList();


        array.stream().collect(Collectors.groupingBy((x)->{
            JSONObject json = (JSONObject)x;
            return "confirm".equals(json.getString("STATE")) ? "confirm" : "qualityTest";
        })).forEach((k,v) ->{
            Map listMap = new HashMap();
            List planList = v.stream().map(item -> {
                JSONObject jItem = (JSONObject)item;

                JSONObject resultJson = new JSONObject();
                resultJson.put("id",jItem.getString("ID"));
                resultJson.put("appOrderId","appOrder".equals(jItem.getString("SOURCE_BUSINESS_TYPE")) ? jItem.getString("SOURCE_FROM") : null);
                return resultJson;
            }).collect(Collectors.toList());
            if("confirm".equals(k)){ //tip
                listMap.put("tip","有单据还在服务中,请确认");
                listMap.put("planList",planList);
            }else if("qualityTest".equals(k)){
                listMap.put("tip","有单据未收款,请确认");
                listMap.put("planList",planList);
            }
            list.add(listMap);
        });

        return MapUtil.mapper("tipFlag",array.size() == 0 ? false : true , "tipList",list);
    }

    @FuncAlias(name = "获取接车人")
    public List<String> findPickUpCarCreator(String deptId,String fnCustomerExpandId) {
        List<PickUpCar> pickUpCarList = pickUpCarRepository.findByDeptIdAndFnCustomerExpandIdOrderByCreateDateDesc(deptId, fnCustomerExpandId);
        if (!pickUpCarList.isEmpty()){
            return userService.findUserByPartyRoleId(pickUpCarList.stream().findFirst().get().getCreator());
        }
        return null;
    }

    /***
     * 功能： 修改
     * @param request
     * @return
     */
    public Map updateDetectionStatus(SimpleRequest request) {
        String id = request.get("id");
        String detectionStatus = request.get("detectionStatus");
        PickUpCar pickUpCarTow = pickUpCarRepository.findOne(id);
        pickUpCarTow.setDetectionStatus(detectionStatus);
        pickUpCarTow = pickUpCarRepository.saveAndFlush(pickUpCarTow);
        return MapUtil.mapper("id",pickUpCarTow.getId(),"detectionStatus",pickUpCarTow.getDetectionStatus());
    }

    private Object findGetCarLog(SimpleRequest request){
        JSONObject jo = request.getJO();
        List<Map> newCondition = getConditionMap(request);

        JSONObject conditionModel = jo.getJSONObject("conditionModel");
        JSONObject customerCar = conditionModel.getJSONObject("customerCar");
        Assert.notNull(customerCar,"车辆信息为空,请重新选出车辆或者刷新页面重试");
        String carLicense = customerCar.getString("carLicense");
        String mainPlan = conditionModel.getString("id");
        JSONObject node = conditionModel.getJSONObject("node");
        String source = conditionModel.getJSONObject("node")==null?mainPlan:node.getString("ID");
        Post post = SpringManager.getBean(PostRepository.class).findOne(request.getPostId());
        Dept dept =post==null?null: post.getDept();
        ServicePlan servicePlan = source==null?null:SpringManager.getBean(ServicePlanRepository.class).findOne(source);

        if (carLicense!=null)newCondition.add(MapUtil.mapper("field", "licenseNumber", "operator", "EQ", "value", carLicense));
        if (dept!=null)newCondition.add(MapUtil.mapper("field", "dept", "operator", "EQ", "value", dept));

        List<PickUpCar> pickUpCars =
                pickUpCarRepository.findAll(
                        JpaDsl.toCriteria(newCondition),new Sort(Sort.Direction.DESC, "createDate")
                );
        List<Map> collect = pickUpCars.stream().map(pickUpCar -> mapper(
                "id", pickUpCar.getId(),
                "state", pickUpCar.getState(),
                "creator", pickUpCar.getCreator() == null ? null : userRepository.findByOrigin(pickUpCar.getCreator()).getName(),
                "mileage", pickUpCar.getMileage(),
                "fuelMeter", pickUpCar.getFuelMeter().getDescription(),
                "keyNumber", pickUpCar.getKeyNumber(),
                "mainPlan", mainPlan,
                "source", source,
                "pickCarType", pickUpCar.getInnerBusinessType(),
                "createDate", DateUtil.format(pickUpCar.getCreateDate(), DateUtil.SHOW_DATETIME_FORMAT)
        )).collect(Collectors.toList());
        List<InnerPickDeliveryUpCar> pickDeliveryUpCars = SpringManager.getBean(InnerPickDeliveryUpCarRepository.class).findAll(JpaDsl.toCriteriaIgnoreNull(
                "state", "EQ", "get",
                "otherSideDept", "EQ", servicePlan==null?dept:servicePlan.getBelongDept(),
                "licenseNumber", "EQ", carLicense));
        List<Map> mapList = pickDeliveryUpCars.stream()
                .map(innerPickDeliveryUpCar -> innerPickDeliveryUpCar.getInnerPickDeliveryUpCarItemList().stream().filter(innerPickDeliveryUpCarItem -> innerPickDeliveryUpCarItem.getNodeDescription().equals("get")).findFirst().orElse(null))
                .filter(Objects::nonNull)
                .map(innerPickDeliveryUpCarItem -> mapper(
                        "id", innerPickDeliveryUpCarItem.getInnerPickDeliveryUpCar().getId(),
                        "state", "内协接车",
                        "creator", innerPickDeliveryUpCarItem.getOperateUid() == null ? null : innerPickDeliveryUpCarItem.getOperateUid().getName(),
                        "mileage", innerPickDeliveryUpCarItem.getMileage(),
                        "fuelMeter", innerPickDeliveryUpCarItem.getFuelMeter().getDescription(),
                        "keyNumber", "",
                        "mainPlan", mainPlan,
                        "source", source,
                        "pickCarType", innerPickDeliveryUpCarItem.getInnerPickDeliveryUpCar().getInnerBusinessType(),
                        "createDate", DateUtil.format(innerPickDeliveryUpCarItem.getOperateDate(), DateUtil.SHOW_DATETIME_FORMAT)
                )).collect(Collectors.toList());
        collect.addAll(mapList);
        PageImpl page = new PageImpl<>(collect, PageRequest.of(request.get("page"), collect.size()+1), collect.size());
        return page;
    }

    private List<Map> getConditionMap(SimpleRequest request) {
        List<Map> condition = request.get("condition");
        List<Map> newCondition = new ArrayList<>();

        condition.forEach(obj ->{
            boolean target = true;
            Map map = new HashMap(obj);
            if ("getCatType".equals(map.get("field"))){
                if ("all".equals(map.get("value")))target=false;
            }
            if ("state".equals(map.get("field"))){
                if ("all".equals(map.get("value")))target=false;
            }
            if(target)newCondition.add(obj);
        });
        return newCondition;
    }


    /**
     * 输入： asc
     * 输出： a%s%c
     * @param str
     * @return
     */
    public String regexSplit(String str){
        String result = "";
        for(int i = 0;i<str.length();i++){
            if(i==0){
                result = result  + "%" + str.charAt(i) ;
            }else {
                result = result + "%" + str.charAt(i)  + "%";
            }
        }
        return result;
    }
}
